/***************************************************************************************************
  *Copyright(C),2010-2016,Sumscope
  *FileName	:  JsonWriter.cpp
  *Author	:  scofined.qi
  *Version	:  1.0
  *Date		:  2016/09/12
  *Desc		:  //用于主要说明此程序文件完成的主要功能
  *Relation :  
  *Others	:  //其他内容说明
  *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
  *History	:  //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
***************************************************************************************************/
#include "include/JsonWriter.h"

namespace qb {
	typedef base::JsonWriter::Element Element;
	static  const Element	COMMA = ',';
	static 	const Element	SEMICOLON = ':';
	static 	const Element	LIST_START = '[';
	static 	const Element	LIST_END = ']';
	static 	const Element	MAP_START = '{';
	static 	const Element	MAP_END = '}';
	static  const Element   QUOTATION = '"';

	base::JsonWriter::JsonWriter(int initCapcity /*= 0*/) :m_count(0), m_finished(false), m_rootmap(false), m_rootlist(false),
		m_format(false), m_level(0)
	{
		initCapcity = (initCapcity > 0 && initCapcity < 16 * 1024 * 1024) ? initCapcity : 0;
		m_buffer = new Buffer(initCapcity);
	}

	base::JsonWriter::~JsonWriter()
	{
		if (m_buffer)
		{
			delete m_buffer;
			m_buffer = NULL;
		}	
	}
	void base::JsonWriter::Reset()
	{
		// 保留内存反复使用
		m_count = 0;
		m_finished = false;
		m_rootmap = false;
		m_rootlist = false;
		m_format = false;
		m_level = 0;
		m_buffer->Reset();
	}
	int base::JsonWriter::GetCapcity() const
	{
		return m_buffer->getcapcity();
	}

	void base::JsonWriter::Start(int capcity)
	{
		m_count = 0;
		m_finished = false;
		m_buffer->clear();
		m_buffer->setcapcity(capcity);
		memset(m_buffer->GetBuffer(), 0, m_buffer->getcapcity() * sizeof(Element));
		AddString(&MAP_START, 1);
	}
	void base::JsonWriter::SeekPos(int pos)
	{
		m_buffer->remove_tail(pos);
	}
	const base::JsonWriter::Element* base::JsonWriter::c_str()
	{
		if (!m_finished)
		{
			m_finished = true;
			if (!m_rootmap && !m_rootlist)
				AddString(&MAP_END, 1);
		}
		return m_buffer->GetBuffer();
	}

	int base::JsonWriter::size()
	{
		if (!m_finished)
		{
			m_finished = true;
			if (!m_rootmap && !m_rootlist)
				AddString(&MAP_END, 1);
		}
		return m_buffer->size();
	}

	base::JsonWriter::Writer* base::JsonWriter::AddMap(const Element* name)
	{
		if (m_count > 0)AddString(&COMMA, 1);
		AddName(name, 0); AddString(&SEMICOLON, 1);
		m_count++;
		return this;
	}

	base::JsonWriter::Writer* base::JsonWriter::AddList(const Element* name)
	{
		if (m_count > 0)AddString(&COMMA, 1);
		AddName(name, 0); AddString(&SEMICOLON, 1);
		m_count++;
		return this;
	}
	void base::JsonWriter::AddNewLine()
	{
		if (!m_format)return;
		AddString("\r\n", 2);
		for (int i = 0; i < m_level; i++)
			AddString("  ", 2);
	}
	void base::JsonWriter::AddName(const Element* name, int len /*= 0*/)
	{
		AddString(&QUOTATION, 1);
		AddString(name, len);
		AddString(&QUOTATION, 1);
	}

	void base::JsonWriter::AddJsonString(const Element* str, int len /*= 0*/)
	{
		AddString(&QUOTATION, 1);
		len = str ? (len <= 0 ? strlen(str) : len) : 0;
		if (len > 0)
		{
			for (int i = 0; i < len; i++)
			{
				const Element& t = str[i];
				if (t == (Element)'\\' || t == (Element)'"') { m_buffer->Add((Element)'\\'); m_buffer->Add(t); }
				else if (t == (Element)'\r') { m_buffer->Add((Element)'\\'); m_buffer->Add((Element)'r'); }
				else if (t == (Element)'\n') { m_buffer->Add((Element)'\\'); m_buffer->Add((Element)'n'); }
				else m_buffer->Add(t);
			}
		}
		AddString(&QUOTATION, 1);
	}

	void base::JsonWriter::AddString(const Element* str, int len /*= 0*/)
	{
		if (str)
		{
			len = len <= 0 ? strlen(str) : len;
			if (len > 0)
				m_buffer->append(str, len);
		}
	}

	void base::JsonWriter::JsonWriterList::End()
	{
		if (m_writer)
		{
			if (m_count <= 0)
				m_writer->AddString(&LIST_START, 1);
			else
				m_writer->AddNewLine();
			m_writer->AddString(&LIST_END, 1);
			m_writer->SetLevel(m_writer->GetLevel() - 1);
		}
		m_writer = 0;
	}

	void base::JsonWriter::JsonWriterList::AddHead()
	{
		m_writer->AddString(m_count <= 0 ? &LIST_START : &COMMA, 1); m_count++;
		m_writer->AddNewLine();
	}

	void base::JsonWriter::JsonWriterMap::End()
	{
		if (m_writer)
		{
			if (m_count <= 0)
				m_writer->AddString(&MAP_START, 1);
			else
				m_writer->AddNewLine();
			m_writer->AddString(&MAP_END, 1);
			m_writer->SetLevel(m_writer->GetLevel() - 1);
		}
		m_writer = 0;
	}

	void base::JsonWriter::JsonWriterMap::AddHead()
	{
		m_writer->AddString(m_count <= 0 ? &MAP_START : &COMMA, 1);
		m_writer->AddNewLine();
		m_count++;
	}

	void base::JsonWriter::JsonWriterMap::AddHeadAndName(const Element* name, int len)
	{
		AddHead();
		m_writer->AddName(name, len); m_writer->AddString(&SEMICOLON, 1);
	}

}
